// SPDX-License-Identifier: GPL-2.0+

#include <common.h>
#include <usb.h>
#include <led.h>
#include <wdt.h>
#include <asm/io.h>

#include <dm.h>
#ifdef CONFIG_DM_VIDEO
#include <video_console.h>
#include <video_font.h>
#endif
#include <mach/ls1x.h>

#include "platform.h"

int __weak ls1x_board_late_init(void)
{
	return 0;
}

int checkboard(void)
{
	printf("Board: %s\n", CONFIG_LOONGSON_BOARD_NAME);
	return 0;
}

int __weak vidconsole_notice(char *notice)
{
#ifdef CONFIG_DM_VIDEO
	struct vidconsole_priv *priv;
	struct udevice *con;
	int col, row, len, ret;

	for (uclass_first_device(UCLASS_VIDEO_CONSOLE, &con);
				con; uclass_next_device(&con)) {
		priv = dev_get_uclass_priv(con);
#if 1
		//显示bootloader版本信息
		{
		char buf[DISPLAY_OPTIONS_BANNER_LENGTH] = {0};
		display_options_get_banner(false, buf, DISPLAY_OPTIONS_BANNER_LENGTH);
		len = strcspn(buf, "\n");
		buf[len] = 0;
		col = (priv->cols / 2) - (len / 2);
		if (col < 0)
			col = 0;
		row = priv->rows - 1;
		vidconsole_position_cursor(con, col, row);
		vidconsole_put_string(con, buf);
		}
#endif

		//显示操作按键提示信息
		len = strlen(notice);
		col = (priv->cols / 2) - (len / 2);
		if (col < 0)
			col = 0;
		row = priv->rows - 2;
		vidconsole_position_cursor(con, col, row);
		vidconsole_put_string(con, notice);
		vidconsole_position_cursor(con, 0, 0);
	}
#endif
	return 0;
}

static void print_notice(void)
{
	char notice[DISPLAY_OPTIONS_BANNER_LENGTH];

	sprintf(notice, "Press %s, %s", NOTICE_STR1, NOTICE_STR2);

	//显示屏控制台显示提示信息
	vidconsole_notice(notice);
	//串口控制台显示提示信息
	printf("********Notice********\n");
	printf("%s\r\n", notice);
	printf("**********************\n");
}

int board_late_init(void)
{
	if (IS_ENABLED(CONFIG_LED)) {
		led_default_state();
	}

	print_notice();
	ls1x_board_late_init();

	return 0;
}

#if defined(CONFIG_USB)
static void ls1x_usb_init(void)
{
#if defined(CONFIG_CPU_LOONGSON1A)
	/* enable USB */
	*(volatile int *)0xbfd00420 &= ~0x200000;
	/*ls1a usb reset stop*/
	*(volatile int *)0xbff10204 |= 0x40000000;
#elif defined(CONFIG_CPU_LOONGSON1B)
	/* enable USB */
	*(volatile int *)0xbfd00424 &= ~0x800;
	/*ls1b usb reset stop*/
	*(volatile int *)0xbfd00424 |= 0x80000000;
#elif defined(CONFIG_CPU_LOONGSON1C)
	*(volatile int *)0xbfd00424 &= ~(1 << 31);
	udelay(100);
	*(volatile int *)0xbfd00424 |= (1 << 31);
#endif
}
#endif

#if defined(CONFIG_LOONGSON_GMAC) || defined(CONFIG_ETH_DESIGNWARE)
static void ls1x_set_gmac(void)
{
#if defined(CONFIG_CPU_LOONGSON1A)
#ifdef LOONGSON_GMAC0_EN
	*((volatile unsigned int*)0xbfd00420) &= ~0x00800000;	/* 使能GMAC0 */
	#ifdef LOONGSON_GMAC0_100M
	*((volatile unsigned int*)0xbfd00420) |= 0x500;		/* 配置成百兆模式 */
	#else
	*((volatile unsigned int*)0xbfd00420) &= ~0x500;		/* 否则配置成千兆模式 */
	#endif
#endif
#ifdef LOONGSON_GMAC1_EN
	*((volatile unsigned int*)0xbfd00420) &= ~0x01000000;	/* 使能GMAC1 */
	#ifdef LOONGSON_GMAC1_100M
	*((volatile unsigned int*)0xbfd00420) |= 0xa00;		/* 配置成百兆模式 */
	#else
	*((volatile unsigned int*)0xbfd00420) &= ~0xa00;		/* 否则配置成千兆模式 */
	#endif
	#ifdef GMAC1_USE_UART01
	*((volatile unsigned int*)0xbfd00420) |= 0xc0;
	#else
	*((volatile unsigned int*)0xbfd00420) &= ~0xc0;
	#endif
#endif
#elif defined(CONFIG_CPU_LOONGSON1B)
	/* 寄存器0xbfd00424有GMAC的使能开关 */
#ifdef LOONGSON_GMAC0_EN
	*((volatile unsigned int*)0xbfd00424) &= ~0x1000;	/* 使能GMAC0 */
	#ifdef LOONGSON_GMAC0_100M
	*((volatile unsigned int*)0xbfd00424) |= 0x5;		/* 配置成百兆模式 */
	#else
	*((volatile unsigned int*)0xbfd00424) &= ~0x5;	/* 否则配置成千兆模式 */
	#endif
#endif
	/* GMAC1初始化 使能GMAC1 和UART0复用，导致UART0不能使用 */
#ifdef LOONGSON_GMAC1_EN
	*((volatile unsigned int*)0xbfd00420) |= 0x18;
	*((volatile unsigned int*)0xbfd00424) &= ~0x2000;	/* 使能GMAC1 */
	#ifdef LOONGSON_GMAC1_100M
	*((volatile unsigned int*)0xbfd00424) |= 0xa;		/* 配置成百兆模式 */
	#else
	*((volatile unsigned int*)0xbfd00424) &= ~0xa;	/* 否则配置成千兆模式 */
	#endif
#endif
#elif defined(CONFIG_CPU_LOONGSON1C)
	*((volatile unsigned int *)0xbfd00424) &= ~(7 << 28);
#ifdef LOONGSON_GMAC_RMII
	*((volatile unsigned int *)0xbfd00424) |= (1 << 30); //wl rmii
#endif
#endif
}
#endif

#ifdef CONFIG_ARCH_EARLY_INIT_R
int arch_early_init_r(void)
{
#if defined(CONFIG_LOONGSON_GMAC) || defined(CONFIG_ETH_DESIGNWARE)
	ls1x_set_gmac();
#endif
#if defined(CONFIG_USB)
	ls1x_usb_init();
#endif
	return 0;
}
#endif

#ifdef CONFIG_RECOVER
extern int recover(void);
#endif

#ifdef CONFIG_LAST_STAGE_INIT
int last_stage_init(void)
{
	/* start usb so that usb keyboard can be used as input device */
	if (CONFIG_IS_ENABLED(USB_KEYBOARD)) {
		usb_init();
	}

	/* 上电时长按按钮3秒进入recover功能, recover优先顺序usb>mmc>sata
       按键使用CONFIG_RECOVER_GPIO_BUTTON定义的gpio */
#ifdef CONFIG_RECOVER
	recover();
#endif

	return 0;
}
#endif

#if defined(CONFIG_SYS_CONSOLE_IS_IN_ENV) && \
defined(CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE)
int overwrite_console(void)
{
	env_set("stdout", "serial");

	return 0;
}
#endif

void arch_preboot_os(void)
{
#ifdef CONFIG_WATCHDOG
	wdt_stop(gd->watchdog_dev);
#endif
}
